<?php

/**
 * Created by PhpStorm.
 * User: bob
 * Date: 2021/4/2
 * Time: 14:33
 */

namespace App\Api\Account\Services;


use App\Api\Account\Models\BusinessTransaction;
use App\Api\Account\Models\UserAccount;
use App\Api\Account\Models\UserAccountTransaction;
use App\Api\Account\Models\UserVip;
use DB;
use App\User;
use Carbon\Carbon;

class BusinessService
{
    public static function transaction($game, $amount, $source, $sourceId, $poundage=0, $memo='')
    {
        $userId = data_get($game, 'user_id', '');
        \DB::beginTransaction();
        $userAccount = UserAccount::where('user_id', '=', $userId)->lockForUpdate()->first() ?: UserAccount::create(['user_id' => $userId, 'balance' => 0]);
        if ($amount == 0) {
            \DB::commit();
            return $userAccount->balance;
        }

        $tmp = bcadd($amount, $poundage, 2);
        $balance = $userAccount->balance;
        $userAccount->balance += $tmp;
        // 判断账户余额不足的标准: 当前余额+信用额度-扣款金额<0
        if (($userAccount->balance) < 0) {
            \DB::rollBack();

            throw new \LogicException("用户余额({$balance}元)不足", 509);
        }
        $userAccount->save();

        if ($amount > 0) {
            $type = 1;
        } else {
            $type = 2;
        }
//        $package = GamePackage::find($packageId);
        $m = BusinessTransaction::create([
            'user_id' => $userId,
            'total' => $amount,
            'source_id' => $sourceId,
            'source' => $source,
            'type' => $type,
            'start_balance' => $balance,
            'end_balance' => $userAccount->balance,
            'payment_status' => 100,
            'poundage' => $poundage,
//            'arrive_time' => Carbon::now()->toDateTimeString(),
            'activity_id' => data_get($game, 'id'),
            'activity_name' => data_get($game, 'name', ''),
//            'package_id' => $packageId,
//            'package_name' => data_get($package, 'package_name', ''),
            'memo' => $memo,
        ]);
        \DB::commit();
        return $m;
    }

    public static function getUserRole($user, $field = 'name')
    {
        $roles = $user->roles()->pluck($field);
        if (!empty($roles)) {
            $roles = $roles->toArray();
        } else {
            $roles = [];
        }
        $user          = $user->toArray();
        $user['roles'] = $roles;
        return $user;
    }


    /**
     * 用户扣费
     * @param $userId
     * @param $amount
     * @param $sourceId
     * @param $sourceType
     * @return mixed
     */
    public static function commonTransaction($userId, $amount, $sourceId, $sourceType, $label='')
    {
        //获取用户信用额度
//        $user = User::where('id', '=', $userId)->select('credit', 'name')->first();

        DB::beginTransaction();
        $userAccount = UserAccount::where('user_id', '=', $userId)->lockForUpdate()->first() ?: UserAccount::create(['user_id' => $userId, 'balance' => 0]);
        if ($amount == 0) {
            DB::commit();
            return $userAccount->balance;
        }

        $balance = $userAccount->balance;
        $userAccount->balance += $amount;
        // 判断账户余额不足的标准: 当前余额+信用额度-扣款金额<0
        if (($userAccount->balance) < 0) {
            DB::rollBack();
            info('用户余额不足', [func_get_args(), $balance]);
            throw new \LogicException("用户余额({$balance}元)不足", 509);
        }
        $userAccount->save();
        $userAccountTransaction = UserAccountTransaction::create([
            'type' => 1,
            'user_id' => $userId,
            'amount' => $amount,
            'source_id' => $sourceId,
            'source_type' => $sourceType,
            'label' => $label,
        ]);
        DB::commit();
        return $userAccount->balance;
    }

    public static function commonIntegralTransaction($userId, $amount, $sourceId, $sourceType, $label='')
    {
        //获取用户信用额度
//        $user = User::where('id', '=', $userId)->select('credit', 'name')->first();

        DB::beginTransaction();
        $userAccount = UserAccount::where('user_id', '=', $userId)->lockForUpdate()->first() ?: UserAccount::create(['user_id' => $userId, 'integral' => 0]);
        if ($amount == 0) {
            DB::commit();
            return $userAccount->integral;
        }

        $balance = $userAccount->integral;
        $userAccount->integral += $amount;
        // 判断账户余额不足的标准: 当前余额+信用额度-扣款金额<0
        if (($userAccount->integral) < 0) {
            DB::rollBack();
            info('用户积分不足', [func_get_args(), $balance]);
            throw new \LogicException("用户余额({$balance}元)不足", 509);
        }
        $userAccount->save();
        $userAccountTransaction = UserAccountTransaction::create([
            'type' => 2,
            'user_id' => $userId,
            'amount' => $amount,
            'source_id' => $sourceId,
            'source_type' => $sourceType,
            'label' => $label,
        ]);
        DB::commit();
        return $userAccount->integral;
    }

    public static function freezeTransaction($userId, $amount, $sourceId, $sourceType, $label='')
    {
        //获取用户信用额度
//        $user = User::where('id', '=', $userId)->select('credit', 'name')->first();

        DB::beginTransaction();
        $userAccount = UserAccount::where('user_id', '=', $userId)->lockForUpdate()->first() ?: UserAccount::create(['user_id' => $userId, 'integral' => 0]);
        if ($amount == 0) {
            DB::commit();
            return $userAccount->freeze;
        }

        $balance = $userAccount->freeze;
        $userAccount->freeze += $amount;
        // 判断账户余额不足的标准: 当前余额+信用额度-扣款金额<0
        if (($userAccount->freeze) < 0) {
            DB::rollBack();
            info('用户冻结的余额不足', [func_get_args(), $balance]);
            throw new \LogicException("用户余额({$balance}元)不足", 509);
        }
        $userAccount->save();
        $userAccountTransaction = UserAccountTransaction::create([
            'type' => 3,
            'user_id' => $userId,
            'amount' => $amount,
            'source_id' => $sourceId,
            'source_type' => $sourceType,
            'label' => $label,
        ]);
        DB::commit();
        return $userAccount->freeze;
    }

    public static function attacheVip($user, $days, $int)
    {
        $now = Carbon::now()->toDateTimeString();
        $userVip = UserVip::where('user_id', '=', $user->id)
            ->orderBy('end', 'desc')
            ->first();

        $expiration = data_get($userVip, 'end', '');

        if (empty($expiration)) {
            $expiration = $now;
        }
        $startAt = $expiration;
        if ($now >= $expiration) {
            $startAt = $now;
        }
        $userVip = UserVip::create([
            'user_id' => $user->id,
            'start' => $startAt,
            'end' => Carbon::parse($startAt)->addDays($days)->toDateTimeString(),
//            'product_id' => ''
        ]);

        self::refreshVip($user);
//        User::find(data_get($user, 'id'))
//            ->update([
//                'vip_expiration' => Carbon::parse($startAt)->addDays($days)->toDateTimeString(),
//            ]);

        self::commonIntegralTransaction(data_get($user, 'id'), $int, 0, 'attache_vip', '充值vip');

        return $userVip;
    }

    public static function refreshVip($user)
    {
        $now = Carbon::now()->toDateTimeString();
        $userVip = UserVip::where('user_id', '=', $user->id)
//            ->where('start', '<=', $now)
//            ->where('end', '>', $now)
            ->get();
        $levelVar = 0;
        $title = '';
        foreach ($userVip as $v) {
            $r = collect(config('vip.products', []))->where('id', (string)data_get($v, 'product_id', ''))->first();
            $level = data_get($r, 'level', '');
            if ($level > $levelVar) {
                $levelVar = $level;
                $title = data_get($r, 'title', '');
            }
        }
            User::find(data_get($user, 'id'))
                ->update([
                    'vip_level' => $title,
                    'vip_level_int' => $levelVar,
                ]);

        $userVip = UserVip::where('user_id', '=', $user->id)
            ->orderBy('id', 'desc')
            ->first();

        if (!empty($userVip)) {
            User::find(data_get($user, 'id'))
                ->update([
                    'vip_expiration' => data_get($userVip, 'end', ''),
                ]);
        }
    }

}
